<template>
  <el-dialog
    v-model="dialogVisible"
    width="35%"
    :before-close="handleClose"
    title="编辑"
  >
    <el-form ref="formNode" :model="formData" :rules="formDataRules">
      <el-form-item label="名称" prop="name">
        <el-input v-model="formData.name" placeholder="" />
      </el-form-item>

      <el-form-item label="描述" prop="descript">
        <el-input v-model="formData.descript" type="textarea" :autosize="{ minRows: 5 }" />
      </el-form-item>

      <el-form-item label="权限" class="supplement-rights-check">
        <el-tree
          ref="treeNodeInfo"
          :data="showTree"
          show-checkbox
          node-key="treeKey"
          highlight-current
          @node-click="onItemNodeClick"
          @check="onCheckClick"
        />

        <!-- 待选项 -->
        <section class="role-edit-check-box">
          <div v-show="showRightCheckBox">
            <el-checkbox
              v-model="overwritAll"
              :indeterminate="isIndeterminate"
              @change="handleCheckAllChange"
            >
              全部
            </el-checkbox>
            <el-checkbox-group
              v-model="nowRights"
              @change="handleCheckedRightsChange"
            >
              <el-checkbox v-for="(tip, lab) of pageRight" :key="lab" :label="lab">
                {{ tip }}
              </el-checkbox>
            </el-checkbox-group>
          </div>
        </section>
      </el-form-item>
    </el-form>

    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmEdit()">保存</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import { ref, defineExpose, computed, reactive, nextTick, watch } from 'vue'
import { allRouter } from '@/router/index'
import { pageRight } from '@/utils/fixedness'
import { roleRouter } from '@/types/shimInterface'

interface baseNode {
  path: string
  label: string
}

interface pathNode extends baseNode {
  children: pageNode[]
}

interface pageNode extends baseNode {
  parentPath: string // 上级标识
  rights: string[]
  treeKey: string
}

interface simplePage {
  path: string
  parentPath: string
}

type treeType = string | boolean | number


// ------------------------------------------------- 页面选择

// 空白权限, 用于初始化
const localAllRouter = allRouter.slice(3)

const showTree: pathNode[] = reactive([])

const userRights: roleRouter = reactive({})

/** 初始化 页面树结构 */
const initBaseTree = () => {
  showTree.length = 0

  for (const path in userRights) {
    delete userRights[path]
  }

  localAllRouter.forEach(first => {

    userRights[first.path] = {}

    const pageRights: pageNode[] = []

    first.children?.forEach(child => {
      userRights[first.path][child.path] = []
      pageRights.push({
        path: child.path,
        parentPath: first.path,
        label: <string>child.meta!.title,
        rights: [],
        treeKey: `${first.path}/${child.path}`
      })
    })

    showTree.push({
      path: first.path,
      label: <string>first.meta!.title,
      children: pageRights
    })
  })
}
initBaseTree()


/** 树形图节点 */
const treeNodeInfo = ref()

/** 点击单个 --配置当前角色, 在当前页面的权限 */
const onItemNodeClick = (item: pathNode | pageNode) => {

  // 单个页面
  if ('rights' in item) {
    showRightCheckBox.value = true
    nowPage.value.path = item.path
    nowPage.value.parentPath = item.parentPath
  } else {
    showRightCheckBox.value = false
  }

}

// 点击复选框 --配置角色可查看的页面
let backTreePath: string[] = []
const onCheckClick = (curClick: pathNode | pageNode, { checkedNodes }: {
  checkedKeys: string[]
  checkedNodes: (pathNode | pageNode)[]
}) => {

  backTreePath.length = 0
  for (const item of checkedNodes) {
    if ('rights' in item) {
      backTreePath.push(`${item.parentPath}#${item.path}`)
    }
  }
}


// ------------------------------------------------- 页面权限
/** 可选项 */
const constrainTerm = Object.keys(pageRight)
/** 部分选择 */
const isIndeterminate = computed(() => {
  // 有选择
  const first = nowRights.value.length > 0
  // 选择数量, 小于总数
  const second = nowRights.value.length < constrainTerm.length
  return first && second
})


/** 是否展示权限选择框 */
const showRightCheckBox = ref(false)
/** 正在编辑的页面 */
const nowPage = ref(<simplePage>{
  path: '',
  parentPath: ''
})
/** 当前选中页面对应的权限 */
const nowRights = computed({
  get() {
    sertainExist()
    return userRights?.[nowPage.value.parentPath]?.[nowPage.value.path] ?? []
  },
  set(nd) {

    if (!userRights[nowPage.value.parentPath]) {
      userRights[nowPage.value.parentPath] = {}
    }
    userRights[nowPage.value.parentPath][nowPage.value.path] = nd

    const alreadyCheck:string[] = treeNodeInfo.value.getCheckedKeys(true)
    const targetPath = `${nowPage.value.parentPath}/${nowPage.value.path}`
    if (!alreadyCheck.includes(targetPath)) {
      const localRight = alreadyCheck.map(treeKey => ({ treeKey }))
      localRight.push({ treeKey: targetPath })
      treeNodeInfo.value.setCheckedNodes(localRight)
    }
  }
})

/** 动态计算, 是否全选状态 */
const overwritAll = computed({
  get() {
    const hasCheck = nowRights.value.length > 0
    const checkAll1 = nowRights.value.length === constrainTerm.length
    return hasCheck && checkAll1
  },
  set() {
    userRights[nowPage.value.parentPath][nowPage.value.path] = [...constrainTerm]
  }
})

/** 确定key必定存在 */
const sertainExist = () => {
  const { path, parentPath } = nowPage.value

  if (!(path && parentPath)) {
    return
  }

  if (!userRights[parentPath]) {
    userRights[parentPath] = {}

    if (!userRights[path]) {
      userRights[parentPath][path] = []
    }
  }

  const targetKey = `${parentPath}#${path}`
  if (!backTreePath.includes(targetKey)) {
    backTreePath.push(targetKey)
  }
}

/** 全选 */
const handleCheckAllChange = (val: treeType ) => {

  if (val) {
    nowRights.value = [...constrainTerm]
  } else {
    nowRights.value.length = 0
  }

}

/** 单选 */
const handleCheckedRightsChange = (value: treeType[]) => {
  nowRights.value = [...<string[]>value]
}

/** 权限回显 */
const echoRights = (pending: roleRouter) => {

  const temp = []
  for (const parentPath in pending) {
    for (const childPath in pending[parentPath]) {
      userRights[parentPath][childPath].push(...pending[parentPath][childPath])
      temp.push({ treeKey: `${parentPath}/${childPath}` })
      backTreePath.push(`${parentPath}#${childPath}`)
    }
  }
  treeNodeInfo.value!.setCheckedNodes(temp)
}

// ------------------------------------------------- 确认环节
const formNode = ref()
/** 待提交数据 */
const formData = reactive({
  name: '',
  descript: '',
  rights: ''
})

/** 表单校验 */
const formDataRules = {
  name: [{ required: true, message: '角色, 总要有个名字吧...', trigger: ['blur', 'change'] }],
  descript: [{ required: true, message: '简单描述一下角色吧...', tirgger: ['change', 'blur'] }]
}

/** 保存 */
const confirmEdit = async() => {

  // 校验表单是否通过
  await formNode.value.validate()

  const finalTree: roleRouter = {}
  for (const treePath of backTreePath) {

    const [k1, k2] = treePath.split('#')

    if (finalTree[k1]) {
      finalTree[k1][k2] = userRights[k1][k2]
    } else {
      finalTree[k1] = { [k2]: userRights[k1][k2] }
    }
  }

  console.log('整理后', finalTree)

}

const dialogVisible = ref(false)
/** 关闭前 提示 */
const handleClose = (done: () => void) => {

  // 调用函数, 才关闭弹窗
  done()
}

// ------------------------------------------------- 其余部分

watch(dialogVisible, async nd => {
  if (nd) {

    await nextTick()
    // TODO 数据回显
    echoRights({ '/img-module': { 'mouse-track': ['OPERATE', 'DOWNLOAD'] } })
  } else {

    // TODO 清空状态
    treeNodeInfo.value!.setCheckedNodes([], false)
    initBaseTree()
    backTreePath.length = 0
    showRightCheckBox.value = false
    nowPage.value.parentPath = ''
    nowPage.value.path = ''
    formData.name = ''
    formData.descript = ''
    formData.rights = ''
  }
})

defineExpose({ dialogVisible })
</script>

<style lang="scss" scoped>

.supplement-rights-check {

  .el-form-item__content {
    $localMaxHeight: 300px;

    &>* {
      flex: 1;
    }

    .el-tree {
      height: $localMaxHeight;
      overflow-y: auto;
    }

    .role-edit-check-box {
      align-self: flex-start;
      padding-left: 20px;
    }
  }

}
</style>
